package net.wicp.tams.plugin;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;

import javassist.ClassPool;
import javassist.NotFoundException;
import net.wicp.tams.common.Conf;
import net.wicp.tams.common.Result;
import net.wicp.tams.common.apiext.CollectionUtil;
import net.wicp.tams.common.apiext.IOUtil;
import net.wicp.tams.common.apiext.StringUtil;
import net.wicp.tams.common.constant.BasePath;
import net.wicp.tams.common.http.HttpClient;
import net.wicp.tams.common.http.HttpResult;
import net.wicp.tams.common.thread.ThreadPool;
import net.wicp.tams.plugin.constant.EnvName;

public abstract class TaskAssit {

	private static boolean isDebug = true;

	/**
	 * 得到资源的绝对路径
	 * 
	 * @return path
	 */
	public static String getInitPath(String resourceDir) {
		if (isDebug) {
			return "file:/D:/greensoft/maven/repo-home/net/wicp/tams/ts-maven-plugin/3.6.1/ts-maven-plugin-3.6.1.jar!/";// 调试用
		} else {
			return TaskAssit.class.getResource(resourceDir).getPath();// 生产用
		}
	}

	public static void proProjectFile(Log log, String oriClassPath, BasePath destBase, String destPath,
			String... replace) {
		try {
			String oriStr = IOUtil.slurp(IOUtil.fileToInputStream(oriClassPath, TaskAssit.class));
			IOUtil.replaceFileByStr(oriStr, destBase, destPath, replace);
			log.info("-------------------生成[" + destPath + "]文件成功-------------------------");
		} catch (Exception e) {
			log.error("-------------------生成[" + destPath + "]文件失败-------------------------", e);
		}
	}

	/**
	 * 把整个目录生成到目标目录
	 * 
	 * @param relaPath
	 *            relaPath
	 * @param destBase
	 *            destBase
	 * @param destRelaPath
	 *            destRelaPath
	 * @param filePrefix
	 *            文件名前缀
	 * @param replace
	 *            replace
	 * @throws Exception
	 *             Exception
	 * @throws IOException
	 *             exception
	 */
	public static void proProjectFileForDir(String relaPath, String destRelaPath, String filePrefix, BasePath destBase,String resourceDir,
			String... replace) throws Exception, IOException {
		Map<String, InputStream> k8s = IOUtil.getFilesFromJar("jar:" + getInitPath(resourceDir), relaPath);
		for (String key : k8s.keySet()) {
			int lastindex = key.lastIndexOf("/");
			String fileName = lastindex > 0 ? key.substring(lastindex + 1) : key;
			if (StringUtil.isNotNull(filePrefix)) {
				fileName = filePrefix + "-" + fileName;
			}
			String oriStr = IOUtil.slurp(k8s.get(key));
			IOUtil.replaceFileByStr(oriStr, destBase, IOUtil.mergeFolderAndFilePath(destRelaPath, fileName), replace);
		}
	}

	// 把项目的类加到classpool
	public static void addProjectClassPath(MavenProject project, ClassPool pool) throws NotFoundException {
		if (project == null || pool == null) {
			return;
		}
		String outputPath = project.getBuild().getOutputDirectory();
		pool.appendClassPath(outputPath);
		Set<Artifact> allJars = project.getArtifacts();
		for (Artifact artifact : allJars) {
			File file = artifact.getFile();
			pool.appendClassPath(file.getPath());
		}
	}

	public static Set<String> findSubClassByProject(Log log, final String parentClassName, MavenProject project,
			final ClassPool pool) throws Exception {
		final Set<String> sublist = new HashSet<>();
		if (project == null || pool == null) {
			return sublist;
		}
		String outputPath = project.getBuild().getOutputDirectory();
		List<String> dirlist = IOUtil.getSubTypeFromDir(outputPath, null, parentClassName, pool);
		sublist.addAll(dirlist);

		Set<Artifact> allJars = project.getArtifacts();
		List<Artifact> listall = new ArrayList<>();
		listall.addAll(allJars);
		int threadnum = 60;
		List<List<Artifact>> inputlist = CollectionUtil.splitListN(listall, threadnum);
		List<Future<Result>> furlist = new ArrayList<>();

		for (final List<Artifact> list : inputlist) {
			FutureTask<Result> aa = new FutureTask<Result>(new Callable<Result>() {

				@Override
				public Result call() throws Exception {
					for (Artifact artifact : list) {
						try {
							File file = artifact.getFile();
							List<String> templist = IOUtil.getSubType(file.getPath(), null, parentClassName, pool);
							sublist.addAll(templist);
						} catch (Exception e) {
							return Result.getError(String.format("[%s]执行失败", Thread.currentThread().getName()));
						}
					}
					return Result.getSuc(String.format("[%s]执行成功", Thread.currentThread().getName()));
				}
			});
			furlist.add(aa);
			ThreadPool.getDefaultPool().submit(aa);
		}
		for (Future<Result> future : furlist) {
			if (future.get().isSuc()) {
				log.info(future.get().getMessage());
			} else {
				log.info(future.get().getMessage());
			}
		}
		return sublist;
	}

	/***
	 * 检查环境变量
	 * 
	 * @param keys
	 *            环境变量
	 * @return 结果
	 */
	public static Result checkEnv(String... keys) {
		List<String> loseKey = new ArrayList<>();
		for (String key : keys) {
			String value = System.getenv(key);
			if (StringUtil.isNull(value)) {
				loseKey.add(key);
			}
		}
		if (loseKey.size() == 0) {
			return Result.getSuc();
		} else {
			return Result.getError(CollectionUtil.listJoin(loseKey, ","));
		}
	}

	// 发送回调信息
	public static HttpResult sendMsg(Log log, String url, String msgid,boolean issuc) {
		try {
			if (StringUtil.isNull(url)) {
				Result checkRet = TaskAssit.checkEnv(EnvName.boomCallbackUrl);
				if (!checkRet.isSuc()) {
					String msg = String.format("如果没有传url参数，可以设置环境变量'boom_callback_url'为回调的地址", checkRet.getMessage());
					log.warn(msg);
					return null;
				}
				url = System.getenv(EnvName.boomCallbackUrl);
			}
			if (StringUtil.isNotNull(url)) {
				if (StringUtil.isNull(msgid)) {
					log.warn("缺少msgid不会回调接口");
					return null;
				}
			}
			if (url.indexOf("?") > 0) {
				url = String.format("%s&msgid=%s&issuc=%s", url, msgid,issuc);
			} else {
				url = String.format("%s?msgid=%s&issuc=%s", url, msgid,issuc);
			}
			HttpResult ret = HttpClient.doGet(url);
			log.info("回调地址调用成功:" + url);
			return ret;
		} catch (Exception e) {
			log.error("回调地址调用失败:" + url);
			return null;
		}
	}

	// k8s初始化 masterurl
	public static void initMasterUrl(String url) throws MojoFailureException {
		Properties overValues = new Properties();
		if (StringUtil.isNull(url)) {
			Result checkRet = TaskAssit.checkEnv(EnvName.k8sMasterUrl);
			if (!checkRet.isSuc()) {
				String msg = String.format("如果没有传url参数，需要在环境变量设置'k8s_master_url'为apiserver的地址", checkRet.getMessage());
				throw new MojoFailureException(msg);
			}
			overValues.setProperty("common.others.kubernetes.master.url", System.getenv(EnvName.k8sMasterUrl));
		} else {
			overValues.setProperty("common.others.kubernetes.master.url", url);
		}
		Conf.overProp(overValues);
	}

	public static void initDockerUrl(String url) throws MojoFailureException {
		Properties overValues = new Properties();
		if (StringUtil.isNull(url)) {
			Result checkRet = TaskAssit.checkEnv(EnvName.dockerUrl);
			if (!checkRet.isSuc()) {
				String msg = String.format("如果没有传url参数，需要在环境变量设置'docker_url'为docker的地址", checkRet.getMessage());
				throw new MojoFailureException(msg);
			}
			overValues.setProperty("common.others.docker.url", System.getenv(EnvName.dockerUrl));
		} else {
			overValues.setProperty("common.others.docker.url", url);
		}
		Conf.overProp(overValues);
	}

}
